package com.sunny.ynhz.model;

import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.google.gson.Gson;
import com.sunny.ynhz.R;
import com.sunny.ynhz.api.ApiService;
import com.sunny.ynhz.api.HttpManager;
import com.sunny.ynhz.api.upload.DefaultProgressListener;
import com.sunny.ynhz.api.upload.RetrofitUtil;
import com.sunny.ynhz.api.upload.UploadFileRequestBody;
import com.sunny.ynhz.app.GlobalVal;
import com.sunny.ynhz.bean.LocationBean;
import com.sunny.ynhz.bean.PathUploadBean;
import com.sunny.ynhz.bean.PatrolBean;
import com.sunny.ynhz.db.RealmUtils;
import com.sunny.ynhz.ui.SinglePixelActivity;
import com.sunny.ynhz.utils.AlertUtilsType;
import com.sunny.ynhz.utils.AppManager;
import com.sunny.ynhz.utils.CarUtils;
import com.sunny.ynhz.utils.FileUtils;
import com.sunny.ynhz.utils.SPUtil;
import com.sunny.ynhz.utils.ShowUtils;
import com.sunny.ynhz.utils.TimeFormatUtils;
import com.sunny.ynhz.utils.TimeIntervalUtils;
import com.sunny.ynhz.utils.ToastUtils;
import com.sunny.ynhz.utils.UUIDUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.realm.Realm;
import okhttp3.RequestBody;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

import static com.sunny.ynhz.utils.ContextUtils.getResources;

/**
 * Created by huhuan123 on 2018/8/29.
 *
 * @describe TODO
 */

public class PatrolModel {
    Context context;
    AMap aMap;
    private Polyline polyline;
    private PolylineOptions polylineOptions;
    private final Realm deleteRealm;
    AlertUtilsType.IClickButton iClickButton;
    private final AlertUtilsType alertDiaoUtils;
    private int minite = 60;
    PatrolBean patrolBean;
    IPatrolModel iPatrolModel;
    private boolean isPatrolIng = false;
    private Marker marker;
    private Marker endMark;
    private Subscription subscribe;
    private final String userId;
    private int validPatrolTime = 30;

    public interface IPatrolModel {
        void patrolRiverTime(String time);

        void distancePatrol(String distance);

        void startPatrolTime(String startTime);

        void lastpatrolRiverTime(String time);

        void lastdistancePatrol(String distance);

        void laststartPatrolTime(String startTime);

    }

    public PatrolModel(Context context, AMap aMap, AlertUtilsType.IClickButton iClickButton, IPatrolModel iPatrolModel) {
        this.context = context;
        this.aMap = aMap;
        this.iPatrolModel = iPatrolModel;
        this.iClickButton = iClickButton;
        deleteRealm = RealmUtils.getDeleteRealm();
        alertDiaoUtils = new AlertUtilsType();
        userId = SPUtil.get("userId", "").toString();
    }

    public PatrolBean getLastPatrolBean() {
        patrolBean = deleteRealm.where(PatrolBean.class).equalTo("isEnd", false).equalTo("userId", SPUtil.get("userId", "").toString()).findFirst();
        if (patrolBean != null) {
            deleteRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    patrolBean.setNeedContinue(true);
                }
            });
        }
        return patrolBean;
    }

    public void disPlayContinuePatrol(String riverName, int type) {
        String msg = "";
        if (riverName.equals("")) {
            msg = "是否开始巡河";
        } else {
            msg = "当前选择的河道是：\n" + riverName;
        }

        alertDiaoUtils.setMsg(msg);
        alertDiaoUtils.setTitle("提示");
        alertDiaoUtils.setEnsureButton("  是  ");
        alertDiaoUtils.setNegativeButton("  否  ");
        alertDiaoUtils.displayDiago(context, iClickButton, type);//代表继续巡河
    }

    public boolean adjustValidPatrol(PatrolBean patrolBean) {
        String patrol_time = SPUtil.get(userId + "patrol_time", "").toString();
        if (!TextUtils.isEmpty(patrol_time)) {
            validPatrolTime = Integer.parseInt(patrol_time);
        }
        if (patrolBean != null) {
            Date dateLast = TimeFormatUtils.StrToDate(patrolBean.getStartTime());
            long timeBetween = (System.currentTimeMillis() - dateLast.getTime()) / 1000;
            if (timeBetween > 60 * validPatrolTime) {
                return true;
            }
        }
        return false;
    }

    public void displayStopPatrolRiver(int type) {
        String msg = "当前巡河未达到" + validPatrolTime + "分钟为无效巡河,是否结束本次巡河";
        alertDiaoUtils.setMsg(msg);
        alertDiaoUtils.setTitle("提示");
        alertDiaoUtils.setEnsureButton("  是  ");
        alertDiaoUtils.setNegativeButton("  否  ");
        alertDiaoUtils.displayDiago(context, iClickButton, type);//代表继续巡河
    }


    public void drawStartMark(LatLng startLatlng) {
        marker = aMap.addMarker(new MarkerOptions().position(startLatlng).title("起点").snippet("起点")
                .draggable(false).icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.begin_marker)))
                .setFlat(true));
    }

    public void drawEndMark(LatLng endLatlng) {
        endMark = aMap.addMarker(new MarkerOptions().position(endLatlng).title("终点").snippet("终点")
                .draggable(false).icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.end_marker)))
                .setFlat(true));
    }

    public void drawPtrolLine(List<LatLng> latLng, AMap aMap) {
        //在这里初始化，每次开始都要有新的轨迹点记录，否则会和之前的轨迹点连起来
        polylineOptions = new PolylineOptions().width(10).color(Color.RED);
        polylineOptions.addAll(latLng);
        polyline = aMap.addPolyline(polylineOptions);
    }

    public void drawLinkLine(LatLng latLng) {
        polylineOptions.add(latLng);
        polyline.setOptions(polylineOptions);
    }

    public int adjustContinuePatrolType(PatrolBean patrolBean) {
        boolean needContinue = patrolBean.isNeedContinue();
        String startTime = patrolBean.getLocationBeanlist().get(patrolBean.getLocationBeanlist().size() - 1).getTime();
        Date dateLast = TimeFormatUtils.StrToDate(startTime);
        long timeBetween = (System.currentTimeMillis() - dateLast.getTime()) / 1000 / 60;
        if (needContinue) {
            if (timeBetween > minite) {
                return 0;//代表超过30分钟

            } else {
                return 1;//没有超过30分钟
            }
        }
        return -1;
    }

    /**
     * 是否提交巡河记录dialog
     */
    public void dialogUploadPatrol() {
        alertDiaoUtils.setEnsureButton("  是  ");
        alertDiaoUtils.setNegativeButton("  否  ");
        alertDiaoUtils.setTitle("系统自动结束巡河提示");
        alertDiaoUtils.setMsg("上次您的APP在巡河时非人为正常关闭，本次距上次已经超过" + minite + "分钟，系统将自动终止上次巡河，是否上传上次巡河记录");
        alertDiaoUtils.displayDiago(context, iClickButton, 2);//
    }

    public void uploadPatrol(PatrolBean patrolBean, String patrolId, String userId, boolean isOnLine, String starttime, String endtime, String riverId, String sectionId, Float distance, boolean isEnd, Double startLgtd, Double startLttd, Double endLgtd, Double endLttd, File file) {
        ApiService uploadFileService = RetrofitUtil.createService(ApiService.class);
        Map<String, RequestBody> requestBodyMap = new HashMap<>();
        UploadFileRequestBody fileRequestBody = new UploadFileRequestBody(file, new DefaultProgressListener(new Handler(), 1));
        requestBodyMap.put("jsonfile\"; filename=\"" + file.getName(), fileRequestBody);
        uploadFileService.uploadPatrol(patrolId, userId, isOnLine, starttime, endtime, riverId, sectionId, distance, isEnd, startLgtd, startLttd, endLgtd, endLttd, requestBodyMap).
                subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread()).
                subscribe(new Subscriber<PathUploadBean>() {
                    @Override
                    public void onStart() {
                        super.onStart();
                        ShowUtils.disPlayProgress(context, "正在上传巡河信息");
                    }

                    @Override
                    public void onCompleted() {
                        ShowUtils.dismissProgress();
                    }

                    @Override
                    public void onError(Throwable e) {
                        ShowUtils.dismissProgress();
                        alertDiaoUtils.setTitle("提示");
                        alertDiaoUtils.setMsg("轨迹上传失败，已存入草稿箱\n请确认网络状况良好后手动上传");
                        alertDiaoUtils.setNegativeButton("我知道了");
                        alertDiaoUtils.setEnsureButton("");
                        alertDiaoUtils.displayDiago(context, iClickButton, 3);//3代表上传路径
                    }

                    @Override
                    public void onNext(PathUploadBean s) {
                        ToastUtils.SingleToastUtil(context, "轨迹上传成功");
                        deleteRealm.executeTransaction(new Realm.Transaction() {
                            @Override
                            public void execute(Realm realm) {
                                patrolBean.setUploaded(true);
                                patrolBean.setEnd(true);
                            }
                        });

                    }
                });
    }

    public void uploadPatrolWithoutFile(PatrolBean patrolBean, String patrolId, String userId, final boolean isOnLine, String starttime, String endtime, String riverId, String sectionId, Float distance, final boolean isEnd, Double startLgtd, Double startLttd, Double endLgtd, Double endLttd) {
        HttpManager.getInstance().uploadPatrol(patrolId, userId, isOnLine, starttime, endtime, riverId, sectionId, distance, isEnd, startLgtd, startLttd, endLgtd, endLttd).
                subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread()).
                subscribe(new Subscriber<PathUploadBean>() {
                    @Override
                    public void onStart() {
                        super.onStart();
                        ShowUtils.disPlayProgress(context, "正在同步服务器信息");
                    }

                    @Override
                    public void onCompleted() {

                        ShowUtils.dismissProgress();
                    }

                    @Override
                    public void onError(Throwable e) {
                        ShowUtils.dismissProgress();
                        ToastUtils.SingleToastUtil(context, "与服务器同步失败，正在用离线模式巡河");
                        deleteRealm.executeTransaction(new Realm.Transaction() {
                            @Override
                            public void execute(Realm realm) {
                                patrolBean.setOnline(false);
                            }
                        });
                    }

                    @Override
                    public void onNext(PathUploadBean s) {

                    }
                });
    }

    /**
     * 停止巡河
     */
    public void stopPatrol(boolean uploadPath, PatrolBean patrolBean) {
        savaCurrentPatrol(patrolBean);//保存当前的路径
        deleteRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                int count = patrolBean.getLocationBeanlist().size();
                float distance = 0.0f;//路线距离
                LatLng latLng1;//第一个点
                LatLng latLng2;//第二个点
                for (int i = 1; i < count; i++) {
                    latLng1 = new LatLng(patrolBean.getLocationBeanlist().get(i - 1).getLttd(), patrolBean.getLocationBeanlist().get(i - 1).getLgtd());
                    latLng2 = new LatLng(patrolBean.getLocationBeanlist().get(i).getLttd(), patrolBean.getLocationBeanlist().get(i).getLgtd());
                    float distanceTemp = AMapUtils.calculateLineDistance(latLng1, latLng2);
                    distance = distance + distanceTemp;
                }
                patrolBean.setDistance(distance);
                patrolBean.setEndTime(TimeFormatUtils.getTime());
                patrolBean.setEnd(true);
                patrolBean.setUserId(SPUtil.get("userId", "").toString());
                patrolBean.setNeedContinue(false);
                patrolBean.setEndLttd(patrolBean.getLocationBeanlist().get(count - 1).getLttd());
                patrolBean.setEndLgtd(patrolBean.getLocationBeanlist().get(count - 1).getLgtd());
            }
        });
        if (uploadPath) {
            File tmpJsonFile = FileUtils.createTmpJsonFile(context);
            Gson gson = new Gson();
            File jsonFile = FileUtils.getFileFromBytes(gson.toJson(RealmUtils.getDeleteRealm().copyFromRealm(patrolBean.getLocationBeanlist())), tmpJsonFile.getPath());
            uploadPatrol(patrolBean, patrolBean.getId(), SPUtil.get("userId", "").toString(), patrolBean.isOnline(), patrolBean.getStartTime(), patrolBean.getEndTime(), patrolBean.getRiverId(), patrolBean.getSectionId(), patrolBean.getDistance() / 1000, true, patrolBean.getStartLgtd(), patrolBean.getStartLttd(), patrolBean.getEndLgtd(), patrolBean.getEndLttd(), jsonFile);
        }
    }

    /**
     * 开始巡河
     */
    public void startPatrol(PatrolBean patrolBean) {
        LocationBean locationBean = new LocationBean();
        locationBean.setLgtd(getCurrentPosition().longitude);
        locationBean.setLttd(getCurrentPosition().latitude);
        locationBean.setTime(TimeFormatUtils.getTime());
        addLocaltionLatlng(locationBean, patrolBean);//起点
        uploadPatrolWithoutFile(patrolBean, patrolBean.getId(), SPUtil.get("userId", "").toString(), patrolBean.isOnline(), patrolBean.getStartTime(), patrolBean.getEndTime(), patrolBean.getRiverId(), patrolBean.getSectionId(), null, false, patrolBean.getStartLgtd(), patrolBean.getStartLttd(), patrolBean.getEndLgtd(), patrolBean.getEndLttd());
    }

    public void cleatMap() {
        if (marker != null) {
            marker.remove();
        }
        if (endMark != null) {
            endMark.remove();
        }
        if (polyline != null) {
            polyline.remove();
        }

    }

    public PatrolBean createPatrolBean() {

        LocationBean locationBean = new LocationBean();
        locationBean.setTime(TimeFormatUtils.getTime());
        locationBean.setLttd(getCurrentPosition().latitude);
        locationBean.setLgtd(getCurrentPosition().longitude);
        deleteRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                patrolBean = deleteRealm.createObject(PatrolBean.class, UUIDUtils.getRandomUUID());
                patrolBean.setEnd(false);
                patrolBean.setOnline(true);
                patrolBean.setUploaded(false);
                patrolBean.setStartTime(TimeFormatUtils.getTime());
                patrolBean.setUserId(SPUtil.get("userId", "").toString());
                //添加第一个点
                patrolBean.getLocationBeanlist().add(realm.copyToRealm(locationBean));
                patrolBean.setStartLttd(locationBean.getLttd());
                patrolBean.setStartLgtd(locationBean.getLgtd());
            }
        });
        return patrolBean;
    }


    public List<LatLng> getLastPatrolRiverRoute(PatrolBean patrolBean) {
        List<LatLng> latLngs = new ArrayList<>();
        int count = patrolBean.getLocationBeanlist().size();
        for (int i = 0; i < count; i++) {
            LatLng latLng1 = new LatLng(patrolBean.getLocationBeanlist().get(i).getLttd(), patrolBean.getLocationBeanlist().get(i).getLgtd());
            latLngs.add(latLng1);
        }
        return latLngs;
    }

    public LatLng getCurrentPosition() {
        AMapLocation aMapLocation = GlobalVal.getaMapLocation();
        return new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
    }

    public LatLng getFirstPosition() {
        LocationBean locationBean = patrolBean.getLocationBeanlist().get(0);
        return new LatLng(locationBean.getLttd(), locationBean.getLgtd());

    }

    public LatLng getLastPositionLatlng(PatrolBean patrolBean) {
        if (patrolBean == null) {
            return null;
        }
        if (patrolBean.getLocationBeanlist() != null && patrolBean.getLocationBeanlist().size() >= 1) {
            LocationBean locationBean = patrolBean.getLocationBeanlist().get(patrolBean.getLocationBeanlist().size() - 1);
            return new LatLng(locationBean.getLttd(), locationBean.getLgtd());
        }
        return null;
    }

    public PatrolBean getCurrentPatrolBean() {
        return patrolBean;

    }

    public void addLocaltionLatlng(LocationBean locationBean, PatrolBean patrolBean) {
        deleteRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                patrolBean.getLocationBeanlist().add(locationBean);
            }
        });
    }

    public void setIsPatrolRiver(boolean isPatrolIng) {
        this.isPatrolIng = isPatrolIng;
    }

    public boolean getPatrolRiver() {
        return isPatrolIng;

    }

    public void deleteCurrentPatrolBean(PatrolBean patrolBean) {
        deleteRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                patrolBean.deleteFromRealm();
            }
        });
    }

    public LatLng getFirstPositionData(PatrolBean patrolBean) {
        LocationBean locationBean = patrolBean.getLocationBeanlist().get(patrolBean.getLocationBeanlist().size() - 1);
        return new LatLng(locationBean.getLttd(), locationBean.getLgtd());
    }

    public void startTimeKeeper(PatrolBean patrolBean) {
        subscribe = Observable.interval(0, 1, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Long>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Long aLong) {
                if (patrolBean != null) {
                    Date dateLast = TimeFormatUtils.StrToDate(patrolBean.getStartTime());
                    long time = dateLast.getTime();
                    String distance = CarUtils.getInstanceCarutils().getDistance(patrolBean.getLocationBeanlist());
                    String stringTime = TimeIntervalUtils.getStringTime(time, System.currentTimeMillis());
                    String startTime = patrolBean.getStartTime().substring(5, patrolBean.getStartTime().length());
                    iPatrolModel.patrolRiverTime(stringTime);
                    iPatrolModel.startPatrolTime(startTime);
                    iPatrolModel.distancePatrol(distance);
                }
            }
        });
    }

    public void setLastPatrolMsg() {
        String distanceStr = SPUtil.get("lastDistance" + SPUtil.get("userId", "").toString(), "暂无信息").toString();
        String timeStr = SPUtil.get("lastPatroltime" + SPUtil.get("userId", "").toString(), "暂无信息").toString();
        String lastTime = SPUtil.get("lastStartTime" + SPUtil.get("userId", "").toString(), "暂无信息").toString();
        iPatrolModel.lastdistancePatrol(distanceStr);
        iPatrolModel.laststartPatrolTime(lastTime);
        iPatrolModel.lastpatrolRiverTime(timeStr);
    }

    public void stopTimeKeeper() {
        if (subscribe != null) {
            subscribe.unsubscribe();
        }
    }

    public void savaCurrentPatrol(PatrolBean patrolBean) {
        Date dateLast = TimeFormatUtils.StrToDate(patrolBean.getStartTime());
        long time = dateLast.getTime();
        String distance = CarUtils.getInstanceCarutils().getDistance(patrolBean.getLocationBeanlist());
        String stringTime = TimeIntervalUtils.getStringTime(time, System.currentTimeMillis());
        String startTime = patrolBean.getStartTime().substring(5, patrolBean.getStartTime().length());
        SPUtil.put("lastPatroltime" + userId, stringTime);
        SPUtil.put("lastDistance" + userId, distance);
        SPUtil.put("lastStartTime" + userId, startTime);
    }


}
